package com.avecsys.quotemanager.service.supplier;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.avecsys.quotemanager.constants.BusinessCodes;
import com.avecsys.quotemanager.dao.common.EnumDBRecordStatus;
import com.avecsys.quotemanager.dao.common.EnumTransactionStatus;
import com.avecsys.quotemanager.dao.supplier.SupplierMasterDAO;
import com.avecsys.quotemanager.dao.user.UserMasterDAO;
import com.avecsys.quotemanager.exception.BusinessException;
import com.avecsys.quotemanager.exception.DAOException;
import com.avecsys.quotemanager.pojos.SupplierMasterPojo;
import com.avecsys.quotemanager.pojos.SupplierUsersPojo;
import com.avecsys.quotemanager.pojos.UserMasterPojo;
import com.avecsys.quotemanager.service.security.CryptoService;
import com.avecsys.quotemanager.utils.TransactionStatus;
import com.avecsys.quotemanager.vo.SupplierVO;

/**
 * @author Sam Sundar K
 */
public class SupplierMasterServiceImpl implements SupplierMasterService
{

	private static final Log log = LogFactory.getLog(SupplierMasterServiceImpl.class);

	private SupplierMasterDAO supplierMasterDAO;

	private UserMasterDAO userMasterDAO;

	private CryptoService cryptoService;

	/**
	 * Method to delete the supplier master information by supplier id
	 * 
	 * @param supplierId
	 * @return TransactionStatus
	 * @throws BusinessException
	 */
	public TransactionStatus deleteSupplierMaster(SupplierMasterPojo supplierMasterPojo)
			throws BusinessException
	{
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.DELETE_FAIL.ordinal());
		try
		{
			transactionStatus = this.supplierMasterDAO.deleteSupplier(supplierMasterPojo);
		}
		catch (DAOException e)
		{
			throw new BusinessException(e);
		}
		return transactionStatus;
	}

	/**
	 * Method to return all the suppliers
	 * 
	 * @return List<SupplierMasterPojo>
	 */
	@Override
	public List<SupplierMasterPojo> getAllSuppliers() throws BusinessException
	{
		try
		{
			return this.supplierMasterDAO.findAllActive(new SupplierMasterPojo());
		}
		catch (DAOException e)
		{
			throw new BusinessException(e);
		}
	}

	@Override
	public List<SupplierUsersPojo> getAllUsers(SupplierMasterPojo supplierMasterPojo)
			throws BusinessException
	{
		try
		{
			return this.userMasterDAO.findAllUsersBySupplier(supplierMasterPojo);
		}
		catch (DAOException e)
		{
			throw new BusinessException(e);
		}
	}

	/**
	 * @return the cryptoService
	 */
	public CryptoService getCryptoService()
	{
		return this.cryptoService;
	}

	/**
	 * Method to get the supplier master information by supplier id
	 * 
	 * @param supplierId
	 * @return SupplierMasterPojo instance
	 * @throws BusinessException
	 */
	@Override
	public SupplierMasterPojo getSupplierMasterById(Long supplierId) throws BusinessException
	{
		SupplierMasterPojo supplierMasterPojo = new SupplierMasterPojo();
		try
		{
			supplierMasterPojo = (SupplierMasterPojo) this.supplierMasterDAO.findActiveById(
					supplierMasterPojo,
						supplierId);
		}
		catch (DAOException e)
		{
			throw new BusinessException(e);
		}
		return supplierMasterPojo;
	}

	/**
	 * @return the supplierMasterDAO
	 */
	public SupplierMasterDAO getSupplierMasterDAO()
	{
		return this.supplierMasterDAO;
	}

	/**
	 * @return the userMasterDAO
	 */
	public UserMasterDAO getUserMasterDAO()
	{
		return this.userMasterDAO;
	}

	/**
	 * Method to verify the supplier email is not registered with another supplier.
	 * 
	 * @param supplierVO
	 * @param email
	 * @return boolean
	 * @throws DAOException
	 * @throws BusinessException
	 */
	public boolean isSupplierEmailNotRegistered(SupplierVO supplierVO) throws BusinessException
	{
		boolean isEmailNotRegistered = true;
		try
		{
			SupplierMasterPojo supplierMasterPojo = getSupplierMasterById(supplierVO.getSupplierId());
			List<UserMasterPojo> userMasterPojoList = this.userMasterDAO.findAllActiveSupplierUsersByEmail(supplierVO.getDefaultAdminUserEmail());
			// If Existing supplier
			if ((supplierMasterPojo != null) && supplierMasterPojo.isPersisted())
			{
				for (UserMasterPojo userMasterPojo : userMasterPojoList)
				{
					if (userMasterPojo.getSupplierUsersPojo().size() > 0)
					{
						// Get The supplier associated
						for (SupplierUsersPojo supplierUsersPojo : userMasterPojo.getSupplierUsersPojo())
						{
							// If a different supplier has the same email id t
							if (!supplierUsersPojo.getSupplierMasterPojo()
									.getSupplierId()
									.equals(supplierVO.getSupplierId()))
							{
								isEmailNotRegistered = false;
								break;
							}
							else
							{
								// If Same Supplier and different user has the
								// same email id and in add new supplier user
								// case
								if (supplierVO.getSupplierUserId() == null)
								{
									isEmailNotRegistered = false;
									break;
								}
								else
								{
									// If Edit Supplier User case and the same
									// email is allocated for different user
									// already then
									if (!supplierUsersPojo.getSupplierUserId().equals(
											supplierVO.getSupplierUserId()))
									{
										isEmailNotRegistered = false;
										break;
									}
								}
							}
						}
					}
				}
			}
			else
			{
				// If New Supplier
				for (UserMasterPojo userMasterPojo : userMasterPojoList)
				{
					if (userMasterPojo.getSupplierUsersPojo().size() > 0)
					{
						isEmailNotRegistered = false;
					}
				}
			}
		}
		catch (DAOException e)
		{
			throw new BusinessException(e);
		}
		return isEmailNotRegistered;
	}

	/**
	 * Method to save or update the supplier master information with default administrator user
	 * 
	 * @param supplierVO
	 * @return Integer
	 * @throws BusinessException
	 */
	@Override
	public TransactionStatus saveSupplierMaster(SupplierVO supplierVO) throws BusinessException
	{
		// Initial Transaction state when save operation
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.SAVE_FAIL.ordinal());
		try
		{
			/*
			 * if (!isSupplierEmailNotRegistered(supplierMasterPojo)) {
			 * transactionStatus
			 * .setStatus(EnumTransactionStatus.BUSINESS_FLOW_FAIL .ordinal());
			 * transactionStatus.setErrorFieldName("emailId"); }
			 */
			// Step1:
			// if the Supplier Master information already persisted then update
			// other wise create a new supplier information with default use
			// Mark As Active
			supplierVO.getSupplierMasterPojo().setStatus(EnumDBRecordStatus.ACTIVE.status());
			if (supplierVO.getSupplierMasterPojo().isPersisted())
			{
				// Initial Transaction State when update operation
				transactionStatus.setStatus(EnumTransactionStatus.UPDATE_FAIL.ordinal());
				transactionStatus = this.supplierMasterDAO.updateSupplier(supplierVO.getSupplierMasterPojo());
			}
			else
			{
				// Create New Supplier With Default Administrator
				SupplierUsersPojo supplierUsersPojo = createDefaultAdminInstance(supplierVO);
				supplierVO.getSupplierMasterPojo().getSupplierUsers().add(supplierUsersPojo);
				transactionStatus = this.supplierMasterDAO.saveSupplier(supplierVO.getSupplierMasterPojo());
			}
		}
		catch (DAOException e)
		{
			log.error(e);
			throw new BusinessException(e);
		}
		return transactionStatus;
	}

	/**
	 * @param cryptoService the cryptoService to set
	 */
	public void setCryptoService(CryptoService cryptoService)
	{
		this.cryptoService = cryptoService;
	}

	/**
	 * @param supplierMasterDAO the supplierMasterDAO to set
	 */
	public void setSupplierMasterDAO(SupplierMasterDAO supplierMasterDAO)
	{
		this.supplierMasterDAO = supplierMasterDAO;
	}

	/**
	 * @param userMasterDAO the userMasterDAO to set
	 */
	public void setUserMasterDAO(UserMasterDAO userMasterDAO)
	{
		this.userMasterDAO = userMasterDAO;
	}

	/**
	 * Method to create the default Admin user for the supplier
	 * 
	 * @param supplierVO
	 * @return SupplierUsersPojo instance
	 */
	private SupplierUsersPojo createDefaultAdminInstance(SupplierVO supplierVO)
	{
		// Create User Instance
		UserMasterPojo userMasterPojo = new UserMasterPojo();
		userMasterPojo.setUserName("Admin");
		userMasterPojo.setPassword(this.cryptoService.encryptPassword("password"));
		userMasterPojo.setEmail(supplierVO.getDefaultAdminUserEmail());
		userMasterPojo.setEmailVerfied(Boolean.FALSE.toString());
		userMasterPojo.setStatus(EnumDBRecordStatus.ACTIVE.status());
		userMasterPojo.setUserType(BusinessCodes.USER_TYPE_SUPPLIER);
		// Audit User Information
		userMasterPojo.setCreatedDttm(supplierVO.getSupplierMasterPojo().getModifiedDttm());
		userMasterPojo.setCreatedUserId(supplierVO.getSupplierMasterPojo().getModifiedUserId());
		userMasterPojo.setModifiedDttm(supplierVO.getSupplierMasterPojo().getModifiedDttm());
		userMasterPojo.setModifiedUserId(supplierVO.getSupplierMasterPojo().getModifiedUserId());

		// Create Supplier User Instance
		SupplierUsersPojo supplierUsersPojo = new SupplierUsersPojo();
		supplierUsersPojo.setIsAdmin(Boolean.TRUE.toString());
		supplierUsersPojo.setUserMasterPojo(userMasterPojo);
		supplierUsersPojo.setSupplierMasterPojo(supplierVO.getSupplierMasterPojo());
		supplierUsersPojo.setStatus(EnumDBRecordStatus.ACTIVE.status());

		// Audit User Information
		supplierUsersPojo.setCreatedDttm(supplierVO.getSupplierMasterPojo().getModifiedDttm());
		supplierUsersPojo.setCreatedUserId(supplierVO.getSupplierMasterPojo().getModifiedUserId());
		supplierUsersPojo.setModifiedDttm(supplierVO.getSupplierMasterPojo().getModifiedDttm());
		supplierUsersPojo.setModifiedUserId(supplierVO.getSupplierMasterPojo().getModifiedUserId());
		return supplierUsersPojo;
	}
}
